﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Quark.Profiler.Framework;

namespace Quark.Profiler.Framework.Test
{
    /// <summary>
    /// ProfilingTestCase功能性单元测试
    /// </summary>
    [TestClass]
    public class ProfilingTestCaseUnitTest
    {
        private System.Threading.AutoResetEvent waitHandler;
        private long _starting;
        private long _started;
        private long _finished;
        private long _stopping;
        private long _loopedTimes;

        #region 内部类

        private class ProfilingVisualizerTest : IProfilingVisualizer
        {
            private object syncRoot;
            public List<string> Msg;

            public ProfilingVisualizerTest()
            {
                this.syncRoot = new object();
                this.Msg = new List<string>();
            }

            public string GetLastInfo()
            {
                lock (this.syncRoot)
                {
                    return this.Msg[this.Msg.Count - 1];
                }
            }

            #region IProfilingVisualizer 成员

            public void UpdateProfilingLoopInfo(long loopedTimes, long maxLoopTimes, int lastLoopElapsedTimes)
            {
                string info = string.Format("{0},{1}: {2}", loopedTimes, maxLoopTimes, lastLoopElapsedTimes);

                lock (this.syncRoot)
                {
                    this.Msg.Add(info);
                }
            }

            #endregion
        }

        private class ProfilingContextTest : IProfilingContext
        {
            private object syncRoot;
            public ProfilingVisualizerTest TestCaseVisualizer { get; set; }
            public Dictionary<IProfilingActivity, ProfilingVisualizerTest> Visualizers { get; set; }
            public List<string> Msg { get; set; }

            public ProfilingContextTest()
            {
                this.syncRoot = new object();
                this.TestCaseVisualizer = new ProfilingVisualizerTest();
                this.Visualizers = new Dictionary<IProfilingActivity, ProfilingVisualizerTest>();
                this.Msg = new List<string>();
            }

            public string GetLastMessage()
            {
                lock (this.syncRoot)
                {
                    return this.Msg[this.Msg.Count - 1];
                }
            }

            public string GetMessage(int index)
            {
                lock (this.syncRoot)
                {
                    return this.Msg[index];
                }
            }

            private void AppendMessage(string message)
            {
                lock (syncRoot)
                {
                    this.Msg.Add(message);
                }
            }

            #region IProfilingContext 成员

            public IProfilingVisualizer GetProfilingVisualizer(ProfilingTestCase testCase)
            {
                return this.TestCaseVisualizer;
            }

            public IProfilingVisualizer GetProfilingVisualizer(IProfilingActivity activity)
            {
                lock (this.syncRoot)
                {
                    if (this.Visualizers.ContainsKey(activity)) return this.Visualizers[activity];
                    else
                    {
                        this.Visualizers[activity] = new ProfilingVisualizerTest();
                        return this.Visualizers[activity];
                    }
                }
            }

            public void LogInfo(object sender, string message)
            {
                lock (this.syncRoot)
                {
                    this.Msg.Add(
                        string.Format("{0}@INFO: {1}", sender.GetType().Name, message));
                }
            }

            public void LogProfilingInfo(object sender, string message)
            {
                lock (this.syncRoot)
                {
                    this.Msg.Add(
                        string.Format("{0}@PROFILING: {1}", sender.GetType().Name, message));
                }
            }

            public void LogError(object sender, string message)
            {
                lock (this.syncRoot)
                {
                    this.Msg.Add(
                        string.Format("{0}@ERROR: {1}", sender.GetType().Name, message));
                }
            }

            public void LogException(object sender, string message, Exception exception)
            {
                lock (this.syncRoot)
                {
                    this.Msg.Add(
                        string.Format("{0}@EXCEPTION: {1}, EX: {2}", sender.GetType().Name, message, exception));
                }
            }

            #endregion
        }

        private class TestActivityC11 : ProfilingActivityBase
        {
            public long Count = 0;

            protected override bool DoExecute(IDictionary<string, object> parameters, ProfilingRequest requestParams, ProfilingTestActivityCounter counter)
            {
                System.Threading.Interlocked.Increment(ref Count);
                return true;
            }
        }

        private class TestActivityC12 : ProfilingActivityBase
        {
            public long Count = 0;

            protected override bool DoExecute(IDictionary<string, object> parameters, ProfilingRequest requestParams, ProfilingTestActivityCounter counter)
            {
                System.Threading.Interlocked.Increment(ref Count);
                return true;
            }
        }

        private class TestActivityC13 : ProfilingActivityBase
        {
            public long Count = 0;

            protected override bool DoExecute(IDictionary<string, object> parameters, ProfilingRequest requestParams, ProfilingTestActivityCounter counter)
            {
                System.Threading.Interlocked.Increment(ref Count);
                return true;
            }
        }

        #endregion

        public ProfilingTestCaseUnitTest()
        {
        }

        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，该上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试属性
        //
        // 编写测试时，还可使用以下附加属性:
        //
        // 在运行类中的第一个测试之前使用 ClassInitialize 运行代码
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // 在类中的所有测试都已运行之后使用 ClassCleanup 运行代码
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // 在运行每个测试之前，使用 TestInitialize 来运行代码
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // 在每个测试运行完之后，使用 TestCleanup 来运行代码
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        private void project_OnTestProjectFinished(object sender, ProfilingTestProjectFinishedEventArgs e)
        {
            int ticks = Environment.TickCount;
            e.Context.LogInfo(sender, "project finished: " + ticks.ToString());
            this.waitHandler.Set();
        }

        private void TestActivityManagementTest_OnTestCaseStarting(object sender, ProfilingTestCaseEventArgs e)
        {
            System.Threading.Interlocked.Increment(ref _starting);
        }

        private void TestActivityManagementTest_OnTestCaseFinished(object sender, ProfilingTestCaseFinishedEventArgs e)
        {
            System.Threading.Thread.Sleep(100);
            int ticks = Environment.TickCount;
            e.Context.LogInfo(sender, "testcase finished: " + ticks.ToString());
            System.Threading.Interlocked.Increment(ref _finished);
        }

        private void TestActivityManagementTest_OnTestCaseStopping(object sender, ProfilingTestCaseEventArgs e)
        {
            System.Threading.Interlocked.Increment(ref _stopping);
        }

        private void TestActivityManagementTest_OnTestCaseStarted(object sender, ProfilingTestCaseEventArgs e)
        {
            System.Threading.Interlocked.Increment(ref _started);
        }

        private void TestActivityManagementTest_OnTestCaseLooped(object sender, ProfilingTestCaseLoopedEventArgs e)
        {
            System.Threading.Interlocked.Exchange(ref _loopedTimes, e.LoopedTimes);
        }

        [TestMethod]
        public void TestActivityManagementTest()
        {
            this.waitHandler = new System.Threading.AutoResetEvent(false);
            IProfilingContext context = new ProfilingContextTest();
            ProfilingTestProject project = new ProfilingTestProject(context);
            project.OnTestProjectFinished += new ProfilingTestProjectFinishedHandler(project_OnTestProjectFinished);
            ProfilingTestCase testCase = project.AppendNewTestCase("测试用例", "测试用例描述");
            testCase.OnTestCaseStarting += new ProfilingTestCaseStartingHandler(TestActivityManagementTest_OnTestCaseStarting);
            testCase.OnTestCaseStarted += new ProfilingTestCaseStartedHandler(TestActivityManagementTest_OnTestCaseStarted);
            testCase.OnTestCaseStopping += new ProfilingTestCaseStoppingHandler(TestActivityManagementTest_OnTestCaseStopping);
            testCase.OnTestCaseFinished += new ProfilingTestCaseFinishedHandler(TestActivityManagementTest_OnTestCaseFinished);

            //创建活动测试
            testCase.Activities = new string[] {
                "Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC11, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                ,"Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC12, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                ,"Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC13, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
            };

            this._starting = 0;
            this._started = 0;
            this._finished = 0;
            this._stopping = 0;

            //启动用例
            project.StartTest();
            this.waitHandler.WaitOne();
            Assert.IsTrue(
                (_starting == 1) && (_started == 1) && (_stopping == 0) && (_finished == 1)
                );
            Assert.IsTrue(project.State == ProfilingTestState.Finished);
            IProfilingActivity[] activities = testCase.ProfilingActivityInstances;
            Assert.IsTrue((activities != null) && (activities.Length == 3)
                && (activities[0].GetType().Name.Equals("TestActivityC11"))
                && (activities[1].GetType().Name.Equals("TestActivityC12"))
                && (activities[2].GetType().Name.Equals("TestActivityC13"))
                );
            Assert.IsTrue(
                (((TestActivityC11)activities[0]).Count == 1)
                && (((TestActivityC12)activities[1]).Count == 1)
                && (((TestActivityC13)activities[2]).Count == 1)
                );

            #region Comments

            ////添加用例测试
            //ProfilingTestCase testCase1 = testCase.ap("用例1", "用例1描述");
            //Assert.IsTrue((testCase.Cases.Length == 1) && (testCase.Cases[0] == testCase1), "AppendNewTestCase(string, string)方法空集合添加用例测试失败");
            //ProfilingTestCase testCase2 = testCase.AppendNewTestCase("用例2", "用例2描述");
            //Assert.IsTrue((testCase.Cases.Length == 2) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    , "AppendNewTestCase(string, string)方法非空集合添加用例测试失败");

            ////集合元素移动测试
            //testCase.MoveTestCaseUp(testCase1);
            //Assert.IsTrue((testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2), "对集合第一个元素执行MoveTestCaseUp(...)方法测试失败");
            //testCase.MoveTestCaseUp(testCase2);
            //Assert.IsTrue((testCase.Cases[0] == testCase2) && (testCase.Cases[1] == testCase1), "对集合非第一个元素执行MoveTestCaseUp(...)方法测试失败");
            //testCase.MoveTestCaseDown(testCase2);
            //Assert.IsTrue((testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2), "对集合第一个元素执行MoveTestCaseDown(...)方法测试失败");
            //testCase.MoveTestCaseDown(testCase2);
            //Assert.IsTrue((testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2), "对集合最后一个元素执行MoveTestCaseDown(...)方法测试失败");

            ////进行更多元素的测试
            //ProfilingTestCase testCase3 = testCase.AppendNewTestCase("用例3", "用例3描述");
            //Assert.IsTrue((testCase.Cases.Length == 3) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3),
            //    "AppendNewTestCase(string, string)方法非空集合添加用例测试失败");
            //ProfilingTestCase testCase4 = testCase.AppendNewTestCase("用例4", "用例4描述");
            //Assert.IsTrue((testCase.Cases.Length == 4) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4),
            //    "AppendNewTestCase(string, string)方法非空集合添加用例测试失败");
            //ProfilingTestCase testCase5 = testCase.AppendNewTestCase("用例5", "用例5描述");
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "AppendNewTestCase(string, string)方法非空集合添加用例测试失败");

            //Assert.IsTrue((testCase1 != testCase2) && (testCase1 != testCase3) && (testCase1 != testCase4) && (testCase1 != testCase5));

            ////集合元素移动测试
            //testCase.MoveTestCaseUp(testCase1);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合第一个元素执行MoveTestCaseUp(...)方法测试失败");
            //testCase.MoveTestCaseDown(testCase1);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase2) && (testCase.Cases[1] == testCase1)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合第一个元素执行MoveTestCaseDown(...)方法测试失败");
            //testCase.MoveTestCaseUp(testCase1);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合中间的元素执行MoveTestCaseUp(...)方法测试失败");
            //testCase.MoveTestCaseDown(testCase5);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合最后一个元素执行MoveTestCaseDown(...)方法测试失败");
            //testCase.MoveTestCaseUp(testCase5);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase5) && (testCase.Cases[4] == testCase4),
            //    "对集合最后一个元素执行MoveTestCaseUp(...)方法测试失败");
            //testCase.MoveTestCaseDown(testCase5);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合中间的元素执行MoveTestCaseDown(...)方法测试失败");
            //testCase.MoveTestCaseDown(testCase2);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase3)
            //    && (testCase.Cases[2] == testCase2) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合中间的元素执行MoveTestCaseDown(...)方法测试失败");
            //testCase.MoveTestCaseUp(testCase2);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合中间的元素执行MoveTestCaseUp(...)方法测试失败");
            //testCase.MoveTestCaseUp(testCase4);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase4) && (testCase.Cases[3] == testCase3) && (testCase.Cases[4] == testCase5),
            //    "对集合中间的元素执行MoveTestCaseUp(...)方法测试失败");
            //testCase.MoveTestCaseDown(testCase4);
            //Assert.IsTrue((testCase.Cases.Length == 5) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4) && (testCase.Cases[4] == testCase5),
            //    "对集合中间的元素执行MoveTestCaseDown(...)方法测试失败");

            ////删除集合测试
            //testCase.RemoveTestCase(testCase5);
            //Assert.IsTrue((testCase.Cases.Length == 4) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase2)
            //    && (testCase.Cases[2] == testCase3) && (testCase.Cases[3] == testCase4),
            //    "删除集合元素RemoveTestCase(...)方法测试失败");
            //testCase.RemoveTestCase(testCase2);
            //Assert.IsTrue((testCase.Cases.Length == 3) && (testCase.Cases[0] == testCase1) && (testCase.Cases[1] == testCase3)
            //    && (testCase.Cases[2] == testCase4),
            //    "删除集合元素RemoveTestCase(...)方法测试失败");
            //testCase.RemoveTestCase(testCase1);
            //Assert.IsTrue((testCase.Cases.Length == 2) && (testCase.Cases[0] == testCase3) && (testCase.Cases[1] == testCase4),
            //    "删除集合元素RemoveTestCase(...)方法测试失败");

            ////清空集合测试
            //testCase.ClearTestCases();
            //Assert.IsTrue((testCase.Cases.Length == 0), "清空集合ClearTestCases()方法测试失败");

            #endregion
        }

        [TestMethod]
        public void TestActivityManagementTestMoreLoopTimes()
        {
            this.waitHandler = new System.Threading.AutoResetEvent(false);
            IProfilingContext context = new ProfilingContextTest();
            ProfilingTestProject project = new ProfilingTestProject(context);
            project.OnTestProjectFinished += new ProfilingTestProjectFinishedHandler(project_OnTestProjectFinished);
            ProfilingTestCase testCase = project.AppendNewTestCase("测试用例", "测试用例描述");
            testCase.LoopForever = false;
            testCase.LoopTimes = 10;
            testCase.OnTestCaseStarting += new ProfilingTestCaseStartingHandler(TestActivityManagementTest_OnTestCaseStarting);
            testCase.OnTestCaseStarted += new ProfilingTestCaseStartedHandler(TestActivityManagementTest_OnTestCaseStarted);
            testCase.OnTestCaseStopping += new ProfilingTestCaseStoppingHandler(TestActivityManagementTest_OnTestCaseStopping);
            testCase.OnTestCaseFinished += new ProfilingTestCaseFinishedHandler(TestActivityManagementTest_OnTestCaseFinished);

            //创建活动测试
            testCase.Activities = new string[] {
                "Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC11, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                ,"Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC12, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                ,"Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC13, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
            };

            this._starting = 0;
            this._started = 0;
            this._finished = 0;
            this._stopping = 0;

            //启动用例
            project.StartTest();
            this.waitHandler.WaitOne();
            Assert.IsTrue(
                (_starting == 1) && (_started == 1) && (_stopping == 0) && (_finished == 1)
                );
            Assert.IsTrue(project.State == ProfilingTestState.Finished);
            IProfilingActivity[] activities = testCase.ProfilingActivityInstances;
            Assert.IsTrue((activities != null) && (activities.Length == 3)
                && (activities[0].GetType().Name.Equals("TestActivityC11"))
                && (activities[1].GetType().Name.Equals("TestActivityC12"))
                && (activities[2].GetType().Name.Equals("TestActivityC13"))
                );
            Assert.IsTrue(
                (((TestActivityC11)activities[0]).Count == 10)
                && (((TestActivityC12)activities[1]).Count == 10)
                && (((TestActivityC13)activities[2]).Count == 10)
                );
        }

        [TestMethod]
        public void TestActivityManagementTestLoopForever()
        {
            this.waitHandler = new System.Threading.AutoResetEvent(false);
            IProfilingContext context = new ProfilingContextTest();
            ProfilingTestProject project = new ProfilingTestProject(context);
            project.OnTestProjectFinished += new ProfilingTestProjectFinishedHandler(project_OnTestProjectFinished);
            ProfilingTestCase testCase = project.AppendNewTestCase("测试用例", "测试用例描述");
            testCase.LoopForever = true;
            testCase.OnTestCaseStarting += new ProfilingTestCaseStartingHandler(TestActivityManagementTest_OnTestCaseStarting);
            testCase.OnTestCaseStarted += new ProfilingTestCaseStartedHandler(TestActivityManagementTest_OnTestCaseStarted);
            testCase.OnTestCaseStopping += new ProfilingTestCaseStoppingHandler(TestActivityManagementTest_OnTestCaseStopping);
            testCase.OnTestCaseFinished += new ProfilingTestCaseFinishedHandler(TestActivityManagementTest_OnTestCaseFinished);
            testCase.OnTestCaseLooped += new ProfilingTestCaseLoopedHandler(TestActivityManagementTest_OnTestCaseLooped);

            //创建活动测试
            testCase.Activities = new string[] {
                "Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC11, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                ,"Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC12, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                ,"Quark.Profiler.Framework.Test.ProfilingTestCaseUnitTest+TestActivityC13, Quark.Profiler.Framework.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
            };

            this._starting = 0;
            this._started = 0;
            this._finished = 0;
            this._stopping = 0;

            //启动用例
            project.StartTest();

            System.Threading.Thread.Sleep(2000);
            project.StopTest();
            waitHandler.WaitOne();
            Assert.IsTrue(
                (_starting == 1) && (_started == 1) && (_stopping == 1) && (_finished == 1)
                );

            Assert.IsTrue(project.State == ProfilingTestState.Finished);
            IProfilingActivity[] activities = testCase.ProfilingActivityInstances;
            Assert.IsTrue((activities != null) && (activities.Length == 3)
                && (activities[0].GetType().Name.Equals("TestActivityC11"))
                && (activities[1].GetType().Name.Equals("TestActivityC12"))
                && (activities[2].GetType().Name.Equals("TestActivityC13"))
                );

            Assert.IsTrue(
                (((TestActivityC11)activities[0]).Count == this._loopedTimes)
                && (((TestActivityC12)activities[1]).Count == this._loopedTimes)
                && (((TestActivityC13)activities[2]).Count == this._loopedTimes)
                );
        }
    }
}
